﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Newtonsoft.Json.Linq;
using SharpSoft.Data.DAOS;

namespace SharpSoft.Web
{
    /// <summary>
    /// 行政区域接口
    /// </summary>
    [AllowAnonymous]
    public class DistrictAreaController : BaseController
    {
        public DistrictAreaController(
            ILogger<DistrictAreaController> p_logger,
            IOptions<AppConfig> appconfig, IHttpContextAccessor p_accessor, IWebHostEnvironment p_env, DatabaseService p_databaseService) : base(appconfig, p_accessor, p_env, p_databaseService)
        {
            this.logger = p_logger;
        }


        protected ILogger<DistrictAreaController> logger;

        /// <summary>
        /// 行政区域数据的更新周期
        /// </summary>
        public static TimeSpan UpdateTimeSpan = TimeSpan.FromDays(1);

        /// <summary>
        /// 获取中国省份
        /// </summary> 
        public async Task<ApiResult> GetChinaProvinces()
        {
            return await GetChildrenArea("100000");
        }
        /// <summary>
        /// 获取子区域
        /// </summary>
        /// <param name="pid"></param>
        /// <returns></returns>
        public async Task<ApiResult> GetChildrenArea(string parentCode)
        {
            var ddal = this.dao<DistrictAreaDAO>();
            var dinfo = ddal.GetArea(parentCode);
            if (dinfo == null || (DateTime.Now - dinfo.updateTime >= UpdateTimeSpan && dinfo.level != DistrictAreaLevel.Street))
            {//需要拉取数据或更新(街道级别永远不用更新)
                try
                {
                    var list = await ThirdParty.GaodeWebAPI.District(parentCode, 1, "");
                    if (list == null || list.Count == 0)
                    {
                        logger.LogWarning("【高德地图API】要获取的区域码未反馈数据", parentCode);
                    }
                    var dis = list[0] as JObject;
                    var area = FromGaode(dis);
                    List<DistrictAreaInfo> children = new List<DistrictAreaInfo>();
                    if (dis["districts"].Type == JTokenType.Array)
                    {
                        int index = 1;
                        foreach (JObject item in dis["districts"])
                        {
                            var child = FromGaode(item);
                            if (child.level == DistrictAreaLevel.Street)
                            {//街道级别补上街道索引
                                child.areaCode = $"{child.areaCode}-{index:000}";
                            }
                            children.Add(child);
                            index++;
                        }
                    }

                    ddal.UpdateDistrictArea(area, children);
                }
                catch (Exception ex)
                {
                    logger.LogError("【高德地图API】更新行政区域时发生异常", parentCode, ex);
                }

            }
            var data = ddal.GetChildren(parentCode);

            return Success(data);
        }
        /// <summary>
        /// 获取行政区域链条，如指定沙市区的code则可以获取到(湖北省-荆州市-沙市区)
        /// </summary>
        /// <param name="code"></param>
        /// <returns></returns>
        public ApiResult GetDistrictChain(string code)
        {
            var ddal = this.dao<DistrictAreaDAO>();

            var result = new JObject();
            result["country"] = null;
            result["province"] = null;
            result["city"] = null;
            result["district"] = null;
            result["street"] = null;

            result["countrys"] = null;
            result["provinces"] = null;
            result["citys"] = null;
            result["districts"] = null;
            result["streets"] = null;
            var c = code;
            while (true)
            {
                var area = ddal.GetArea(c);
                switch (area.level)
                {
                    case DistrictAreaLevel.Country:
                        result["country"] = JObject.FromObject(area);
                        result["provinces"] = JArray.FromObject(ddal.GetChildren(c));
                        break;
                    case DistrictAreaLevel.Province:
                        result["province"] = JObject.FromObject(area);
                        result["citys"] = JArray.FromObject(ddal.GetChildren(c));
                        break;
                    case DistrictAreaLevel.City:
                        result["city"] = JObject.FromObject(area);
                        result["districts"] = JArray.FromObject(ddal.GetChildren(c));
                        break;
                    case DistrictAreaLevel.District:
                        result["district"] = JObject.FromObject(area);
                        result["streets"] = JArray.FromObject(ddal.GetChildren(c));
                        break;
                    case DistrictAreaLevel.Street:
                        result["street"] = JObject.FromObject(area);
                        break;
                    case DistrictAreaLevel.None:
                    default:
                        break;
                }
                var pcode = ddal.GetParentCode(c);
                if (string.IsNullOrEmpty(pcode))
                {
                    break;
                }
                c = pcode;
            }

            return Success(result);
        }

        /// <summary>
        /// 从高德地图接口反馈的行政区域数据转换为通用行政区域对象
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        private static DistrictAreaInfo FromGaode(JObject obj)
        {
            if (obj == null)
            {
                return null;
            }
            DistrictAreaInfo areaInfo = new DistrictAreaInfo()
            {
                areaCode = obj["adcode"].ToString(),
                areaName = obj["name"].ToString(),
                center = obj["center"].ToString(),
            };
            if (obj["citycode"].Type == JTokenType.String)
            {
                areaInfo.cityCode = obj["citycode"].ToString();
            }
            switch (obj["level"].ToString())
            {
                case "country":
                    areaInfo.level = DistrictAreaLevel.Country;
                    break;
                case "province":
                    areaInfo.level = DistrictAreaLevel.Province;
                    break;
                case "city":
                    areaInfo.level = DistrictAreaLevel.City;
                    break;
                case "district":
                    areaInfo.level = DistrictAreaLevel.District;
                    break;
                case "street":
                    areaInfo.level = DistrictAreaLevel.Street;
                    break;
                default:
                    break;
            }


            return areaInfo;
        }
    }
}
